/*
 * Copyright (C) Citypassenger Ltd. All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 *
 * You must obey the GNU Affero General Public License in all respects
 * for all of the code used other than OpenSSL.
 */


#include "monit.h"
#include "cervlet.h"
#include "engine.h"
#include "file_list_loader.h"


#include <sys/mman.h> //msync

struct web_pages_process {
        HttpResponse res;
        char* name;
        int done;
};

List_T web_pages = NULL;


void extfile_init() {
        if (web_pages == NULL) {
                web_pages = List_new();
        }
}

void web_pages_print(
    struct web_pages_process* wpp,
    struct file_list_entry* wph) {
        if (!strncasecmp(wph->type, "js", 2)) {
                set_content_type(wpp->res, "application/javascript");
        } else if (!strncasecmp(wph->type, "html", 4)) {
                set_content_type(wpp->res, "text/html");
        } else if (!strncasecmp(wph->type, "gif", 3)) {
                set_content_type(wpp->res, "image/gif");
        } else if (!strncasecmp(wph->type, "ico", 3)) {
                set_content_type(wpp->res, "image/vnd.microsoft.icon");
        } else if (!strncasecmp(wph->type, "jpeg", 4)) {
                set_content_type(wpp->res, "image/jpeg");
        } else if (!strncasecmp(wph->type, "png", 3)) {
                set_content_type(wpp->res, "image/png");
        } else if (!strncasecmp(wph->type, "css", 3)) {
                set_content_type(wpp->res, "text/css");
        } else {
                LogError("%s: cant figure out file type webhome file %s(%s)\n",
                         prog, wpp->name, wph->type);
                set_content_type(wpp->res, "application/octet-stream");
                // char s[32];
                // sprintf(s, "%u", wph->size);
                // set_header(wpp->res, "Content-Length", s);
        }
        msync(wph->map,wph->size,MS_SYNC);
        StringBuffer_append_nstr(wpp->res->outputbuffer,
                  wph->map, wph->size);
}


void print_good_page(void *e, void *ap) {
        struct file_list_entry* wph = e;
        struct web_pages_process* wpp = ap;
        if (wpp->done == 0 && !strncasecmp(wph->name, wpp->name, strlen(wph->name))) {
                LogDebug("%s: getting back, as %s is loaded with %s\n",
                         prog, wph->name, wpp->name);
                wpp->done = 1;
                web_pages_print(wpp,wph);
                return;
        }
}


void do_file(HttpRequest req, HttpResponse res) {
        char* file_name = NULL;
        if ( Run.webfiles != NULL && Run.webhome != NULL &&
             ( strlen(req->url) < 1 || 0 == strcmp(req->url,"") || 0 == strcmp(req->url,"/") || 0 == strncmp(req->url,"/?",2) )
           ) {
                file_name = Str_cat("%s/%s",Run.webfiles, Run.webhome);
        } else {
                file_name = Str_cat("%s/%s",Run.webfiles, req->url);
        }
        //trusting right access lol
        struct web_pages_process wpp = {
                res,
                file_name,
                0
        };
        //if not /_info/service then loadpage;
        List_map(web_pages, print_good_page, &wpp);
        if (wpp.done == 0) {
                struct file_list_entry* fle;
                int rc = open_file(file_name, &fle);
                if (rc) {
                        send_error(res, SC_NOT_FOUND,
                                   "There is no file by that name");
                } else {
                        web_pages_print(&wpp,fle);
                        LogDebug("%s: push %s \n", prog, file_name);
                        List_push(web_pages, fle);
                }
        } else {
                FREE(file_name);
        }
}